/*-----------------------------------------------------------------------------------*/
/*                                                                                   */
/* Copyright (c) 2008 Nuvoton Technology Corporation                                 */
/* All rights reserved                                                               */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/
/* File Contents:                                                                    */
/*   ps2_mouse.c                                                                     */
/*                                                                                   */
/* This file contains:                                                               */
/*                                                                                   */
/* Project:                                                                          */
/*                                                                                   */
/* Remark:                                                                           */
/*   1. In this mouse example, program get the mouse packets by callback function.   */
/*                                                                                   */
/*-----------------------------------------------------------------------------------*/

#ifdef ECOS 
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "kapi.h"
#include "diag.h"
#include "wbio.h"
#else
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wblib.h"
#endif

#include "NUC900_PS2.h"

#ifdef ECOS
#define ps2printf		diag_printf
#define ps2getchar		diag_getc
#else
#define ps2printf		sysprintf
#define ps2getchar		sysGetChar
#endif 

#ifdef ECOS
static cyg_handle_t  	thread_handle;
static cyg_thread 		thread;
#define STACKSIZE		(128*1024)
static UINT8            _Statck[STACKSIZE];
#endif

UINT8 ps2SetScale = 0xE6;
UINT8 ps2SetSampleRate = 0xF3;
UINT8 ps2EnableDataReport = 0xF4;
UINT8 ps2MouseReset = 0xFF;

int port;
volatile int packetcnt = 0;
volatile int gfLeftButton = 0;
volatile int gfRightButton = 0;
volatile int gfMidButton = 0;
volatile int gXmov_flag, gYmov_flag, gXmov_data, gYmov_data; 

unsigned char pktdata[3];

PS2_DATA_T rxb[5];

int MouseStatusDetection (void);

//------------------------- Program -------------------------//
void PS2MouseCallBackDemo (void)
{
	int retval;
	int old_lbutton, old_rbutton, old_mbutton;
	
	packetcnt++;
	
	/* a entire mouse data includes 3 packets */	
	if (packetcnt >= 3)  
	{
		packetcnt -= 3;	
		
		retval = ps2Read(port, (PUINT8)&rxb, 3);
		if (retval == 3)
		{
			pktdata[0] = rxb[0].ucScanCode;
			pktdata[1] = rxb[1].ucScanCode;
			pktdata[2] = rxb[2].ucScanCode;
			
			/* keep old button status */
			old_lbutton = gfLeftButton;
			old_rbutton = gfRightButton;
			old_mbutton = gfMidButton;
			
			/* check button status and movement */
			MouseStatusDetection();
			
			ps2printf("\nMove Packet : \n");	
			
			/* print left button message */
			if (old_lbutton != gfLeftButton)
			{
				ps2printf("     Left button->");
			
				if (gfLeftButton)
					ps2printf("press\n");
				else
					ps2printf("release\n");
			}
		
			/* print right button message */
			if (old_rbutton != gfRightButton)
			{
				ps2printf("     Right button->");
			
				if (gfRightButton)
					ps2printf("press\n");
				else
					ps2printf("release\n");
			}
		
			/* print middle button message */
			if (old_mbutton != gfMidButton)
			{
				ps2printf("     Middle button->");
			
				if (gfMidButton)
					ps2printf("press\n");
				else
					ps2printf("release\n");
			}
		
			/* print X & Y movement message */			
			ps2printf("     X Movement : %c%d\n", (gXmov_flag < 0) ? '-':'+', gXmov_data);							
			ps2printf("     Y Movement : %c%d\n", (gYmov_flag < 0) ? '-':'+', gYmov_data);
			ps2printf("--------------------------------\n");
		}
		else
			ps2printf("Get mouse packet fail!\n");
	}
}

int MouseStatusDetection (void)
{
	/* button status */
	if (pktdata[0] & 0x01)
		gfLeftButton = TRUE;
	else
		gfLeftButton = FALSE;
	
	if (pktdata[0] & 0x02)
		gfRightButton = TRUE;
	else
		gfRightButton = FALSE;
	
	if (pktdata[0] & 0x04)
		gfMidButton = TRUE;
	else
		gfMidButton = FALSE;

	/* X movement */
	if (pktdata[0] & 0x10)
	{
		gXmov_flag = -1;
		gXmov_data = (int) (((~pktdata[1]) + 1) & 0xFF);
	}
	else
	{
		gXmov_flag = 1;											
		gXmov_data = (int) pktdata[1];
	}
	
	/* Y movement */	
	if (pktdata[0] & 0x20)
	{
		gYmov_flag = -1;
		gYmov_data = (int) (((~pktdata[2]) + 1) & 0xFF);
	}
	else
	{
		gYmov_flag = 1;
		gYmov_data = (int) pktdata[2]; 	
	}
		
	return 0;
} 

#ifdef ECOS
void _ps2MouseExample (cyg_addrword_t data)
#else
void _ps2MouseExample ()
#endif
{
	int retval, ch;
	UINT8 rate = 0x28;
		
	ps2printf("\n\nMouse Example ...\n");
	
	while (1)
	{
		ps2printf("\n Select PS2 channel [0/1]\n");
		ch = ps2getchar();
		if ( (ch != '0') && (ch != '1') )
			continue;
		else
		{
			if (ch == '0')
				port = PS2_PORT0;
			else
				port = PS2_PORT1;	
				
			break;	
		}	
	}
	ps2printf(" Channel[%d] selected\n", port);		
	
	ps2Init();
	retval = ps2Open(port, PS2_MOUSE);
	if (retval != 0)
	{
		ps2printf("\n Open PS2 device fail!\n");	
		return;
	}
	
	/* reset mouse */
	retval = ps2Write(port, &ps2MouseReset, 1);
	if (retval < 0)
	{
		ps2printf("\n Reset mouse fail!\n");
		return;
	}
	else
		ps2printf("\n Reset mouse success\n");	
		
	/* configure mouse */
	retval = ps2Write(port, &ps2SetScale, 1);
	if (retval < 0)
		return;
	
	retval = ps2Write(port, &ps2SetSampleRate, 1);
	if (retval < 0)
		return;
	
	retval = ps2Write(port, &rate, 1);  /* 40 samples/sec */
	if (retval < 0)
		return;
	
	retval = ps2Write(port, &ps2EnableDataReport, 1);
	if (retval < 0)
		return;
	
	/* flush PS2 Rx buffer for the following test */
	retval = ps2Ioctl(port, PS2_IOC_FLUSH_RX_BUFFER, 0, 0);
	if (retval != 0)
	{
		ps2printf("\n Flush Rx buffer fail!\n");	
		return;	
	}	
	
	/* 
		For mouse application, non-block mode is recommended. 
	*/
	retval = ps2Ioctl(port, PS2_IOC_SET_RX_MODE, PS2_NON_BLOCK, 0);
	if (retval != 0)
		return;
		
	retval = ps2Ioctl(port, PS2_IOC_SET_CALLBACK_FUN, (UINT32)PS2MouseCallBackDemo, 0);
	if (retval != 0)
		return;	
	
	ps2printf("\n Start to test\n");
	
	while(1);  /* wait for mouse packet */		
	
	return;
}	

int main ()
{


#ifdef ECOS

	cyg_thread_create(20, _ps2MouseExample, 0, "ps2mouse", _Statck, STACKSIZE, &thread_handle, &thread);
	cyg_thread_resume(thread_handle);

#else
	_ps2MouseExample();
#endif	
	
	return 0;	
}